/* eslint-disable no-use-before-define */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import {
  ref,
  Ref,
  watch,
  computed,
  onMounted,
  onUnmounted,
  ComputedRef,
} from 'vue';
import useStore from '../store';
import { debounce } from '../utils';
import {
  IGlobalConfig,
  ITaskViewModel,
  IResourceViewModel,
} from '../interface';
import { calcScheduleByEvtOrDrag } from './use-share';

// 组件样式
export function useScheduleTableStyle(
  props: any,
  hasExtraToolbar: boolean = false,
): {
  headerStyle: ComputedRef<Record<string, string>>;
  bodyStyle: ComputedRef<Record<string, string>>;
  calcTaskStyle: (task: ITaskViewModel) => Record<string, string>;
} {
  // 头部样式
  const headerStyle = computed(() => {
    return {
      width: '100%',
      height: `${props.headerRowHeight * 2}px`,
    };
  });

  // 内容样式
  const bodyStyle = computed(() => {
    return {
      width: '100%',
      height: `calc(100% - ${props.headerRowHeight * 2}px - 40px - ${hasExtraToolbar ? '40px' : '0px'})`,
    };
  });

  // 计算任务项样式
  const calcTaskStyle = (task: ITaskViewModel): Record<string, string> => {
    const _type = task.data.data[props.taskTypeField] || '';
    return {
      taskColor: props.taskColorOptions?.[_type]?.taskColor || props.taskColor,
      taskBgColor:
        props.taskColorOptions?.[_type]?.taskBgColor || props.taskBgColor,
      taskAcitveBorderColor:
        props.taskColorOptions?.[_type]?.taskAcitveBorderColor ||
        props.taskAcitveBorderColor,
    };
  };

  return { headerStyle, bodyStyle, calcTaskStyle };
}

// 初始化调度表格
export function useInitScheduleTable(
  headerCanvas: Ref<HTMLCanvasElement | null>,
  bodyCanvas: Ref<HTMLCanvasElement | null>,
  coordinateElement: Ref<HTMLDivElement | null>,
): {
  resourceViewModels: Ref<IResourceViewModel[]>;
  taskViewModels: Ref<ITaskViewModel[]>;
} {
  const { $config, $bgLayer, $renderLayer, $uiCoordinate } = useStore();

  // 资源视图模型
  const resourceViewModels = computed(() => $renderLayer.resourceViewModels);

  // 任务视图模型
  const taskViewModels = computed(() => $renderLayer.taskViewModels);

  // 挂载
  onMounted(() => {
    if (headerCanvas.value && bodyCanvas.value) {
      $bgLayer.init(headerCanvas.value, bodyCanvas.value);
    }
    if (coordinateElement.value) {
      $uiCoordinate.buildCoordinate(
        coordinateElement.value,
        $renderLayer.getResources(),
      );
      $bgLayer.draw($uiCoordinate, $renderLayer.getResources());
      $renderLayer.buildViewModels($uiCoordinate);
    }
  });

  // 卸载
  onUnmounted(() => {
    $config.destory();
    $uiCoordinate.destory();
    $bgLayer.destory();
    $renderLayer.destory();
  });

  return {
    resourceViewModels,
    taskViewModels,
  };
}

// 通用能力
export function useCommonAbility(
  coordinateElement: Ref<HTMLDivElement | null>,
): {
  refresh: (
    config?: IGlobalConfig,
    resources?: IScheduleResource[],
    tasks?: IScheduleTask[],
  ) => void;
} {
  const { $config, $bgLayer, $renderLayer, $uiCoordinate } = useStore();

  // 刷新界面
  const refresh = (
    config?: IGlobalConfig,
    resources?: IScheduleResource[],
    tasks?: IScheduleTask[],
  ): void => {
    if (!coordinateElement.value) return;
    // 更新数据
    if (config) {
      $config.setConfig(config);
    }
    if (resources) {
      $renderLayer.setResources(resources);
    }
    if (tasks) {
      $renderLayer.setTasks(tasks);
    }
    // 更新绘制
    $uiCoordinate.buildCoordinate(
      coordinateElement.value,
      $renderLayer.getResources(),
    );
    $bgLayer.draw($uiCoordinate, $renderLayer.getResources());
    $renderLayer.buildViewModels($uiCoordinate);
  };

  return {
    refresh,
  };
}

// 处理视图大小变更
export function useScheduleTableReSize(
  props: any,
  headerCanvas: Ref<HTMLCanvasElement | null>,
  bodyCanvas: Ref<HTMLCanvasElement | null>,
  coordinateElement: Ref<HTMLDivElement | null>,
): void {
  const { $uiCoordinate } = useStore();
  // 重绘函数
  const redraw = (): void => {
    const { refresh } = useCommonAbility(coordinateElement);
    if (coordinateElement.value && headerCanvas.value && bodyCanvas.value) {
      // 已经完成布局不需要重绘
      if (coordinateElement.value.clientWidth === $uiCoordinate.canvasWidth)
        return;
      refresh();
    }
  };

  // 防抖重绘函数
  const debouncedRedraw = debounce(redraw, 100);

  // 窗口resize防抖
  const handleResize = (): void => {
    debouncedRedraw();
  };

  // 监听 coordinateElement 的尺寸变化
  let resizeObserver: ResizeObserver | null = null;

  // 挂载后绑定事件监听
  onMounted(() => {
    if (window.ResizeObserver && coordinateElement.value) {
      resizeObserver = new ResizeObserver(handleResize);
      resizeObserver.observe(coordinateElement.value);
    }
  });

  // 移除事件监听器
  onUnmounted(() => {
    if (resizeObserver && coordinateElement.value) {
      resizeObserver.unobserve(coordinateElement.value);
      resizeObserver = null;
    }
  });
}

// 虚拟滚动相关hook
export function useVirtualScroll(
  coordinateElement: Ref<HTMLDivElement | null>,
): {
  visibleRange: Ref<{ start: number; end: number; offsetY: number }>;
  handleScroll: () => void;
} {
  // 可视区域状态
  const visibleRange = ref({
    start: 0,
    end: 0,
    offsetY: 0,
  });

  const { $config, $renderLayer } = useStore();

  // 初始化时计算可见范围
  const initializeVisibleRange = (): void => {
    if (!coordinateElement.value) return;

    const config = $config.getConfig();
    const resources = $renderLayer.getResources();

    const { clientHeight } = coordinateElement.value;
    const itemHeight = config.resourceBodyRowHeight;

    // 计算初始可见范围
    const visibleCount = Math.ceil(clientHeight / itemHeight);
    const end = Math.min(resources.length, visibleCount + 2); // 添加缓冲区

    visibleRange.value = {
      start: 0,
      end,
      offsetY: 0,
    };
  };

  // 滚动时计算可见范围
  const computeVisibleRange = (): void => {
    if (!coordinateElement.value) return;

    const config = $config.getConfig();
    const resources = $renderLayer.getResources();

    const { scrollTop } = coordinateElement.value;
    const { clientHeight } = coordinateElement.value;
    const itemHeight = config.resourceBodyRowHeight;

    // 计算可见范围
    const start = Math.max(0, Math.floor(scrollTop / itemHeight));
    const visibleCount = Math.ceil(clientHeight / itemHeight);
    const end = Math.min(
      resources.length,
      start + visibleCount + 2, // 添加缓冲区
    );

    visibleRange.value = {
      start,
      end,
      offsetY: scrollTop,
    };
  };

  // 资源数据
  const resourceViewModels = computed(() => $renderLayer.resourceViewModels);
  // 在适当的位置添加以下代码
  watch(
    () => resourceViewModels.value.length,
    (newLength, oldLength) => {
      if (newLength !== oldLength) {
        computeVisibleRange();
      }
    },
  );

  onMounted(() => {
    // 使用 setTimeout 确保 DOM 已经渲染完成
    setTimeout(() => {
      initializeVisibleRange();
    }, 0);
  });

  // 滚动事件处理
  const handleScroll = (): void => {
    computeVisibleRange();
  };

  return {
    visibleRange,
    handleScroll,
  };
}

// 工具栏事件
export function useScheduleToolbarEvent(
  coordinateElement: Ref<HTMLDivElement | null>,
): {
  onDataRefresh: (params: any) => void;
  onSave: (params: any) => void;
  onSaveAs: (params: any) => void;
  onConfigRefresh: (params: any) => void;
} {
  const { $config, $renderLayer, $rootEmit } = useStore();
  const { refresh } = useCommonAbility(coordinateElement);
  // 刷新
  const onDataRefresh = (): void => {
    $rootEmit('data-refresh');
  };

  // 保存
  const onSave = (): void => {
    $rootEmit(
      'save',
      $config.getConfig(),
      $renderLayer.getResources(),
      $renderLayer.getTasks(),
    );
  };

  // 另存为
  const onSaveAs = (): void => {
    $rootEmit(
      'saveAs',
      $config.getConfig(),
      $renderLayer.getResources(),
      $renderLayer.getTasks(),
    );
  };

  // 配置刷新
  const onConfigRefresh = (_config: any): void => {
    const config = {
      ...$config.getConfig(),
      ..._config,
    };
    refresh(config);
    $rootEmit('configChange', $config.getConfig());
  };

  return {
    onDataRefresh,
    onSave,
    onSaveAs,
    onConfigRefresh,
  };
}

// 数据更新后刷新界面
export function useScheduleTableDataUpdate(
  props: any,
  coordinateElement: Ref<HTMLDivElement | null>,
): void {
  const { $config } = useStore();
  const { refresh } = useCommonAbility(coordinateElement);

  watch(
    () => [props.resources, props.tasks],
    () => {
      refresh($config.getConfig(), props.resources, props.tasks);
    },
    {
      deep: true,
      immediate: true,
    },
  );

  watch(
    () => props.taskColorOptions,
    () => {
      $config.setConfig({ taskColorOptions: props.taskColorOptions });
    },
    {
      deep: true,
      immediate: true,
    },
  );
}

// 事件处理相关hook
export function useScheduleTableEvent(
  bodyCanvas: Ref<HTMLCanvasElement | null>,
): {
  selectedTaskId: Ref<string | undefined>;
  handleResourceContextMenu: (
    resource: IResourceViewModel,
    event: MouseEvent,
  ) => void;
  handleTaskContextMenu: (task: ITaskViewModel, event: MouseEvent) => void;
  handleCellContextMenu: (event: MouseEvent) => void;
  handleResourceClick: (
    resource: IResourceViewModel,
    event: MouseEvent,
  ) => void;
  handleTaskClick: (task: ITaskViewModel, event: MouseEvent) => void;
  handleCellClick: (event: MouseEvent) => void;
} {
  // 选中任务标识
  const selectedTaskId = ref<undefined | string>();

  // 设置选中任务
  const setSelectTask = (task?: ITaskViewModel): void => {
    selectedTaskId.value = task?.originalId;
  };

  const { $config, $rootEmit } = useStore();
  const handleResourceContextMenu = (
    resource: IResourceViewModel,
    event: MouseEvent,
  ): void => {
    event.preventDefault();
    $rootEmit(
      'contextMenu',
      'resource',
      $config.getConfig(),
      resource.data,
      event,
    );
  };

  const handleTaskContextMenu = (
    task: ITaskViewModel,
    event: MouseEvent,
  ): void => {
    event.preventDefault();
    $rootEmit('contextMenu', 'task', $config.getConfig(), task.data, event);
  };

  const handleCellContextMenu = (event: MouseEvent): void => {
    event.preventDefault();
    const { resource, startDate, position } = calcScheduleByEvtOrDrag(
      event,
      bodyCanvas,
    );
    // 存在开始时间则是单元格触发
    if (startDate) {
      $rootEmit(
        'contextMenu',
        'cell',
        $config.getConfig(),
        { resource: resource?.data, startTime: startDate?.toDate() },
        event,
      );
    } else {
      // 资源列无资源区域触发
      const { x } = position;
      const config = $config.getConfig();
      const { scaleColumnWidth, resourceColumnWidth } = config;
      const resourceAreaLeft = -(resourceColumnWidth + scaleColumnWidth);
      const resourceAreaRight = -scaleColumnWidth;
      if (resourceAreaLeft <= x && x <= resourceAreaRight) {
        $rootEmit('contextMenu', 'resource', config, undefined, event);
      }
    }
  };

  const handleResourceClick = (
    resource: IResourceViewModel,
    event: MouseEvent,
  ): void => {
    setSelectTask();
    $rootEmit(
      'bodyClick',
      'resource',
      $config.getConfig(),
      resource.data,
      event,
    );
  };

  const handleTaskClick = (task: ITaskViewModel, event: MouseEvent): void => {
    setSelectTask(task);
    $rootEmit('bodyClick', 'task', $config.getConfig(), task.data, event);
  };

  const handleCellClick = (event: MouseEvent): void => {
    setSelectTask();
    const { resource, startDate } = calcScheduleByEvtOrDrag(event, bodyCanvas);
    // 存在开始时间则是单元格触发
    if (startDate) {
      $rootEmit(
        'bodyClick',
        'cell',
        $config.getConfig(),
        { resource: resource?.data, startTime: startDate?.toDate() },
        event,
      );
    }
  };

  return {
    selectedTaskId,
    handleResourceContextMenu,
    handleTaskContextMenu,
    handleCellContextMenu,
    handleResourceClick,
    handleTaskClick,
    handleCellClick,
  };
}
